package service.rocksea.com.serviceapp;

import android.util.Log;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by 吴志华 on 2017/10/18.
 *
 */

public class WriteDataThread extends Thread
{
    private DatagramSocket socket;
    private boolean isTurnDown = false;
    private HashMap<Integer, byte[]> todoBytes;

    private Runnable askRunnable;

    public WriteDataThread(DatagramSocket socket)
    {
        this.socket = socket;
        mExecutorService = Executors.newFixedThreadPool(3);
        askRunnable = new Runnable()
        {
            @Override
            public void run()
            {
                while (!isTurnDown)
                {
                    byte[] packet = getLastPacket();
                    if (packet!=null)
                    {
                        try
                        {

                            writePacket(packet);
                        } catch (SocketException e)
                        {
                            e.printStackTrace();
                        }
                    }
                }

            }
        };
        mExecutorService.execute(askRunnable);
    }
    public synchronized void writePacket(byte[] packet) throws SocketException
    {

        synchronized (this)
        {
            if (packet==null||packet.length==0)
                return;
            DatagramPacket datagramPacket = new DatagramPacket(packet,packet.length,new InetSocketAddress("192.168.1.3", CommThread.PHONE_PORT));
            if (socket!=null)
                try
                {
                    socket.send(datagramPacket);
                    Log.i("writePacket: ",getName());
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
        }
    }
    @Override
    public void run()
    {
        super.run();

        while (!isTurnDown)
        {
            try
            {
                byte[] packet = getLastPacket();
                if (packet!=null)
                {
                    writePacket(packet);
                }
            }
            catch (SocketException  e)
            {
                e.printStackTrace();
            }
        }
    }
    public void turnDown()
    {
        isTurnDown = true;
        HeartThread.turnDown();
    }
    private boolean isSendingPlan = true;
    public void sendJson(String json) throws SocketException
    {
        isSendingPlan = false;
        try
        {
            byte[] bytes = json.getBytes("GB2312");
            todoBytes = getBytesMap(bytes);
            UDPPacket udpPackage = new UDPPacket();
            for (Map.Entry<Integer, byte[]> integerEntry : todoBytes.entrySet())
            {
                udpPackage = udpPackage.creatPlanPacket(integerEntry.getValue());
                addPacket(udpPackage.bytes());
            }

            /*while (!(checkPlanPacketIsSendSucess().size()==0))
            {
                if (mSendToDevicePackets.size()==todoBytes.size())
                    return;
                ArrayList<Integer>  unSenedPositions  = checkPlanPacketIsSendSucess();
                for (Integer unSenedPosition : unSenedPositions)
                {
                    udpPackage = udpPackage.creatPlanPacket(todoBytes.get(unSenedPosition));
                    addPacket(udpPackage.bytes());
                }

            }*/
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    private static final int MAX_LENGTH = 492;
    private static final int FILE_FLAG = 12;
    private static final int PACKET_LENGTH = 4;
    private static final int CURRENT_POSITION = 4;

    public HashMap<Integer,byte[]> getBytesMap(byte[] data)
    {
        byte[] idArray = new byte[]{99,0,0,0,0,0,0,0,0,0,0,0};
        byte[] fileLength = intToBytes(data.length);
        int flagLength = FILE_FLAG+PACKET_LENGTH+CURRENT_POSITION;
        byte[] DataArray ;
        HashMap<Integer,byte[]> map = new HashMap<>();
        intBoolenMap = new HashMap<>();
        if(data.length<MAX_LENGTH)
        {
            DataArray = new byte[data.length+flagLength];
            System.arraycopy(idArray,0,DataArray,0,FILE_FLAG);
            System.arraycopy(fileLength,0,DataArray,FILE_FLAG,PACKET_LENGTH);
            System.arraycopy(intToBytes(0),0,DataArray,FILE_FLAG+PACKET_LENGTH,CURRENT_POSITION);
            System.arraycopy(data,flagLength,DataArray,0,data.length);
            map.put(0,data);
            intBoolenMap.put(0,false);
        }
        else
        {
            for (int i = 0; i < data.length / MAX_LENGTH; i++)
            {
                DataArray = new byte[MAX_LENGTH+20];
                System.arraycopy(idArray,0,DataArray,0,12);
                System.arraycopy(fileLength,0,DataArray,12,4);
                System.arraycopy(intToBytes(MAX_LENGTH*i),0,DataArray,16,4);
                System.arraycopy(data,MAX_LENGTH*i,DataArray,20,MAX_LENGTH); //数据数组
                map.put(MAX_LENGTH*i,DataArray);
                intBoolenMap.put(MAX_LENGTH*i,false);
            }
            int leftLength =  data.length%MAX_LENGTH;
            DataArray = new byte[leftLength+20];
            System.arraycopy(idArray,0,DataArray,0,12);
            System.arraycopy(fileLength,0,DataArray,12,4);
            System.arraycopy(intToBytes(MAX_LENGTH*(data.length / MAX_LENGTH)),0,DataArray,16,4);
            System.arraycopy(data,MAX_LENGTH*(data.length / MAX_LENGTH),DataArray,20,leftLength); //数据数组
            map.put(MAX_LENGTH*(data.length / MAX_LENGTH),DataArray);
            intBoolenMap.put(MAX_LENGTH*(data.length / MAX_LENGTH),false);
        }
        byte[] jsonBytes = new byte[data.length];
        for (Map.Entry<Integer, byte[]> integerEntry : map.entrySet())
        {
            int position = integerEntry.getKey();
            byte[] packet = integerEntry.getValue();
            System.arraycopy(packet,20,jsonBytes,position,packet.length-20);
        }
        try
        {
            String json = new String(jsonBytes,"GB2312");
            System.out.println(json);
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
        return map;
    }
    public static byte[] intToBytes(int value)
    {
        ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
        buffer.putInt(value);
        return buffer.array();
    }
    public static byte[] GetBytes(long value) {
        ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
        buffer.putLong(value);
        return buffer.array();
    }

    private ArrayList<Integer> unSenedPositions = new ArrayList<>();
    private HashMap<Integer, Boolean> intBoolenMap;
    private ArrayList<Integer> checkPlanPacketIsSendSucess()
    {
        unSenedPositions.clear();
        if (intBoolenMap==null)
            return unSenedPositions;
        for (Map.Entry<Integer, Boolean> integerBooleanEntry : intBoolenMap.entrySet())
        {
            if (!integerBooleanEntry.getValue())
            {
                unSenedPositions.add(integerBooleanEntry.getKey());
            }
        }
        return unSenedPositions;
    }

    public void handleRequestPlanRespone(UDPPacket udpPackage)
    {
        if (intBoolenMap==null)
            return;
        String machine =udpPackage.getMachineID();
        if (machine==null)
            return;
        byte[] data = udpPackage.DataArray;
        int currentPosition = ToInt32(data,16);
        Log.e("currentPosition", "handleRequestPlanRespone: "+currentPosition);
        intBoolenMap.put(currentPosition,true);
    }


    public static int ToInt32(byte[] bytes, int offset) {
        int result = ByteBuffer.wrap(bytes,(int) offset, 4).order(ByteOrder.LITTLE_ENDIAN).getInt();
        return result;
		/*int result = (int)bytes[offset]&0xFF;
		result |= ((int)bytes[offset+1]&0xFF) << 8;
		result |= ((int)bytes[offset+2]&0xFF) << 16;
		result |= ((int)bytes[offset+3]&0xFF) << 24;

		return result;*/
    }
    private LinkedList<byte[]> mSendToDevicePackets = new LinkedList<>();//待发送的数据链表;
    private synchronized void addPacket(byte[] packet)
    {
        mSendToDevicePackets.addFirst(packet);
    }

    private synchronized byte[] getLastPacket()
    {
        if (mSendToDevicePackets==null||mSendToDevicePackets.size()==0)
            return null;

        return mSendToDevicePackets.pollFirst();
    }

    private ExecutorService mExecutorService;


}
